/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package uk.ac.shef.speech_r25;

/**
 *
 * @author samf
 */

/**
 * Class useful for computing Word Error Rate. 
 * The "computeNumerator" method computes the total number of word deletions, insertions 
 * and substitutions required in order to obtain the "reference" (ref) data
 * starting from "hypothetised" (hyp) data.
 * 
 * @author Maria GEORGESCUL, ISSCO/TIM, ETI, UNIVERSITY OF GENEVA
 *
 */
public class WER  {
	String wordDeliminator = " ";
	String[] ref = new String[0];
	String[] hyp = new String[0];
	

	
	
	/**
	 * 
	 * @param refStr - reference utterance, where each two words are separated by a space
	 * @param hypStr - hypothetised utterance, where each two words are separated by a space
	 * @param wordDeliminator - A string or character used to delimit text into words. Can be a space, a comma, etc.
	 */
	public WER(String refStr, String hypStr, String wordDeliminator){
		this.wordDeliminator = wordDeliminator;
		 ref = refStr.split(wordDeliminator);
		 hyp = hypStr.split(wordDeliminator);
	}
	
	/**
	 * The Word Error rate denominator is just the length (number of words) of reference utterance.   
	 */
	public float computeDenominator() {
			return ref.length;
	}

	/*
	 * Computes the numerator for word error rate. 
	 * That is, the method computes the total number of word deletions, 
	 * insertions and substitutions required in order to obtain the "reference" (ref) data 
	 * starting from "hypothetised" (hyp) data.
	 * The algorithm requires only O(n^2) iterations, where n=max{ref.length, hyp.length}   
	 */
	public float computeNumerator() {
		if ((ref == null) && (hyp==null))
			return 0;
		if ( ( ref.length == 0 ) && (hyp.length ==0 ) )
			return 0;
		if ( ( ref.length == 0 ) && (hyp.length != 0 ) )
			return hyp.length;
		if ( ( ref.length != 0 ) && (hyp.length == 0 ) )
			return ref.length;
		
		int[][] aux = new int[ref.length + 1][hyp.length + 1];

		for (int i = 0; i <= ref.length; i++)
			aux[i][0] = i;
		for (int j = 0; j <= hyp.length; j++)
			aux[0][j] = j;
	
		for (int i = 1; i <= ref.length; i++)
			for (int j = 1; j <= hyp.length; j++)
			{
				int noNewSubst;
				if (ref[i - 1].equals(hyp[j - 1]) )
					noNewSubst = 0;
					else noNewSubst = 1;
				 // take the minimum between the number of deletions required till now (aux[i - 1][j])
//				 // and the number of insertions required till now (aux[i][j - 1])
				int min_aux = 
					Math.min( aux[i - 1][j] + 1,    
							  aux[i][j - 1] + 1);
//				 // also take into account the number of substitutions required till now:
				aux[i][j] = 
					Math.min(min_aux,
							 aux[i - 1][j - 1] + noNewSubst );  					
			}
		return aux[ref.length][hyp.length];


	}

	public String[] getHyp() {
		return hyp;
	}

	public String[] getRef() {
		return ref;
	}

	public void setHyp(String hypStr) {
		 hyp = hypStr.split(" ");

	}

	public void setRef(String refStr) {
		 ref = refStr.split(" ");
	}
}
